package com.boc.ewr.outsrc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.boc.ewr.bcimp.entity.CaBalDtl;
import com.boc.ewr.bcimp.entity.CaRtnList;
import com.boc.ewr.bcimp.entity.CaSendDtl;
import com.boc.ewr.bcimp.service.*;
import com.boc.ewr.outsrc.entity.*;
import com.boc.ewr.outsrc.mapper.OutsrcExpStlmtBatchMapper;
import com.boc.ewr.outsrc.service.*;
import com.boc.ewr.util.file.enumeration.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Description: 费用结算（批量）
 * @Author: jeecg-boot
 * @Date: 2023-06-19
 * @Version: V1.0
 */
@Service
@Slf4j
public class OutsrcExpStlmtBatchServiceImpl extends ServiceImpl<OutsrcExpStlmtBatchMapper, OutsrcExpStlmtBatch> implements IOutsrcExpStlmtBatchService {

    // 重点类 25天
    private Long impStanderDays = 25L;

    // 非重点类 45天
    private Long unImpstanderDays = 45L;

    // 费用标准数据Id
    private static final String COST_ID = "COST-FEE";

    // A=9.5元；B=15.2元；C=11.4元；D=200元；E=100元；F=7.6元；G=100元。
    private String COST_A = "9.5";
    private String COST_B = "15.2";
    private String COST_C = "11.4";
    private String COST_D = "100";
    private String COST_E = "200";
    private String COST_F = "7.6";
    private String COST_G = "100";
    private String ZERO = "0";

    @Autowired
    private IOutsrcDailyProblemService outsrcDailyProblemService;

    @Autowired
    private IOutsrcNdrDtlService outsrcNdrDtlService;

    @Autowired
    private IOutsrcHandoverDtlService outsrcHandoverDtlService;

    @Autowired
    private ICaRtnListService caRtnListService;

    @Autowired
    private ICaBalDtlService caBalDtlService;

    @Autowired
    private IHolidayListService holidayListService;

    @Autowired
    private ICaSendDtlService caSendDtlService;

    @Autowired
    private IOutsrcCostSettingService outsrcCostSettingService;

    @Autowired
    private OutsrcExpStlmtBatchMapper outsrcExpStlmtBatchMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createInfo() {
        this.remove(null);

        List<OutsrcExpStlmtBatch> resultList = outsrcExpStlmtBatchMapper.createInfo();

        this.saveBatch(resultList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<OutsrcExpStlmtBatch> calCost(List<OutsrcExpStlmtBatch> outsrcExpStlmtBatchListh) {
        OutsrcCostSetting byId = outsrcCostSettingService.getById(COST_ID);
        // 初始化费用标准
        COST_A = byId.getCostA();
        COST_B = byId.getCostB();
        COST_C = byId.getCostC();
        COST_D = byId.getCostD();
        COST_E = byId.getCostE();
        COST_F = byId.getCostF();
        COST_G = byId.getCostG();

        outsrcExpStlmtBatchListh.forEach(batch -> {
            log.info("正在为下面数据执行费用生成：" + batch.getId());
            // 回收时间
            genReturnTime(batch);
            // 是否逾期
            genIsDelinquent(batch);
            // 账单状态
            genBillStatus(batch);
            // 费用计算
            countCost(batch);
        });
        return outsrcExpStlmtBatchListh;
    }

    /**
     * 数据优先级 日常问题 > 打包投递 > 账单信息确认 > 交接明细 > 回执信息
     */

    // 用交接明细、账单信息确认明细、最后一次导入的回执信息中的时间
    private void genReturnTime(OutsrcExpStlmtBatch batch) {
        String caNo = batch.getCaNo();
        // 查询交接明细
        List<OutsrcHandoverDtl> outsrcHandoverDtlList = outsrcHandoverDtlService.list(
                new LambdaQueryWrapper<OutsrcHandoverDtl>()
                        .eq(OutsrcHandoverDtl::getCaNo, caNo)
                        .orderByDesc(OutsrcHandoverDtl::getCreateTime)
        );
        if (outsrcHandoverDtlList.size() > 0) {
            OutsrcHandoverDtl outsrcHandoverDtl = outsrcHandoverDtlList.get(0);
            batch.setReturnTime(outsrcHandoverDtl.getCreateTime());

            return;
        }

        // 查询回执查询清单
        List<CaRtnList> caRtnLists = caRtnListService.list(
                new LambdaQueryWrapper<CaRtnList>()
                        .eq(CaRtnList::getCaNo, caNo)
                        .orderByDesc(CaRtnList::getRtnSignDate)

        );

        if (caRtnLists.size() > 0) {
            CaRtnList caRtnList = caRtnLists.get(0);
            batch.setReturnTime(caRtnList.getRtnSignDate());
        }
    }

    //回收时间减去发送时间（账单月份+31天，如遇节假日顺延），重点类按期为≤25天，非重点类≤45天，超过为逾期
    private void genIsDelinquent(OutsrcExpStlmtBatch batch) {
        Date returnTime = batch.getReturnTime();
        if (returnTime == null) {
            return;
        }
        // 发送时间 账单月份+31天
        Date billMon = batch.getBillMon();
        Calendar cal = Calendar.getInstance();
        cal.setTime(billMon);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.DATE, 31);
        Date sendTime = cal.getTime();

        // 获取逾期天数标准
        Long standerDays;
        if (ProtocolTypeEnum.getNoFocusIndexSet().contains(batch.getBillType())) {
            // 非重点类
            standerDays = unImpstanderDays;
        } else {
            standerDays = impStanderDays;
        }

        long countDays = holidayListService.countWorkdays(sendTime, returnTime);

        if (countDays <= standerDays) {
            batch.setIsDelinquent(IsDelinquentEnum.ON_TIME.getIndex());
        } else {
            batch.setIsDelinquent(IsDelinquentEnum.NO_ON_TIME.getIndex());
        }
    }


    private void genBillStatus(OutsrcExpStlmtBatch batch) {
        String caNo = batch.getCaNo();

        // 日常问题（6大问题）
        List<OutsrcDailyProblem> outsrcDailyProblemList = outsrcDailyProblemService.list(
                new LambdaQueryWrapper<OutsrcDailyProblem>()
                        .eq(OutsrcDailyProblem::getCaNo, caNo)
                        .orderByDesc(OutsrcDailyProblem::getCreateTime)

        );

        if (outsrcDailyProblemList.size() > 0) {
            OutsrcDailyProblem outsrcDailyProblem = outsrcDailyProblemList.get(0);
            String problemContent = outsrcDailyProblem.getProblemContent();
            if (ProblemContentEnum.OUTSRC_LOST.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.OUTSRC_LOST.getIndex());
            } else if (ProblemContentEnum.FAKE.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.FAKE.getIndex());
            } else if (ProblemContentEnum.CUSM_COMPLAIN.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.COMPLAIN.getIndex());
            } else if (ProblemContentEnum.CUSM_LOST.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.CUSM_LOST.getIndex());
            } else if (ProblemContentEnum.CUSM_NO_RECEIVE.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.CUSM_UNRECEIVE.getIndex());
            } else if (ProblemContentEnum.CUSM_NO_SEND.getIndex().equals(problemContent)) {
                batch.setBillStatus(BillStatusEnum.CUSM_UNSEND.getIndex());
            }
            return;
        }

        // 打包投递（打包）
        if (YnEnum.YES.getIndex().equals(batch.getIsPackaged())) {
            batch.setBillStatus(BillStatusEnum.PACKED.getIndex());

            return;
        }

        // 账单信息确认（外包退信）
        List<OutsrcNdrDtl> outsrcNdrDtlList = outsrcNdrDtlService.list(
                new LambdaQueryWrapper<OutsrcNdrDtl>()
                        .eq(OutsrcNdrDtl::getCaNo, caNo)
                        .eq(OutsrcNdrDtl::getFdbkStatus, FdbkStatusEnum.FEEDBACK.getIndex())
                        .orderByDesc(OutsrcNdrDtl::getCheckTime)

        );

        if (outsrcNdrDtlList.size() > 0) {
            batch.setBillStatus(BillStatusEnum.OUTSRC_BACK.getIndex());
            return;
        }

        // 交接明细（是否逾期）
        if (IsDelinquentEnum.ON_TIME.getIndex().equals(batch.getIsDelinquent())) {
            batch.setBillStatus(BillStatusEnum.ON_TIME.getIndex());
            return;
        } else if (IsDelinquentEnum.NO_ON_TIME.getIndex().equals(batch.getIsDelinquent())) {
            batch.setBillStatus(BillStatusEnum.NO_ON_TIME.getIndex());
            return;
        }

        // 回执信息（客户自寄）
        List<CaRtnList> caRtnLists = caRtnListService.list(
                new LambdaQueryWrapper<CaRtnList>()
                        .eq(CaRtnList::getCaNo, caNo)
                        // 有效回执状态
                        .in(CaRtnList::getRtnSta, ReturnStatusEnum.getValidIndexSet())
                        .orderByDesc(CaRtnList::getRtnSignDate)

        );
        if (caRtnLists.size() > 0) {
            batch.setBillStatus(BillStatusEnum.CUSM_SELF.getIndex());
            return;
        }

        // 余额对账单（未回）
        long count = caBalDtlService.count(
                new LambdaQueryWrapper<CaBalDtl>()
                        .eq(CaBalDtl::getCaNo, caNo)
        );
        if (count >= 0) {
            batch.setBillStatus(BillStatusEnum.CUSM_SELF.getIndex());
        }
    }

    private void countCost(OutsrcExpStlmtBatch batch) {
        String billStatus = batch.getBillStatus();
        // 外包按期回收
        if (BillStatusEnum.ON_TIME.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(COST_A); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(COST_C); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 外包逾期回收
        else if (BillStatusEnum.NO_ON_TIME.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(COST_A); //回收费用
                batch.setDefaultCharge("-" + COST_D); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(COST_C); //回收费用
                batch.setDefaultCharge("-" + COST_D); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 打包发送 省内9.5除以同一件的份数 省外15.2除以同一件的份数
        else if (BillStatusEnum.PACKED.getIndex().equals(billStatus)) {
            long count = caSendDtlService.count(
                    new LambdaQueryWrapper<CaSendDtl>()
                            .eq(CaSendDtl::getProtocolNo, batch.getProtocolNo())
            );
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                BigDecimal bigDecimal = new BigDecimal(COST_A);
                // 保留两位小数，四舍五入
                BigDecimal result = bigDecimal.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP);

                batch.setDeliveryCharge(result.toString()); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                BigDecimal bigDecimal = new BigDecimal(COST_B);
                // 保留两位小数，四舍五入
                BigDecimal result = bigDecimal.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP);

                batch.setDeliveryCharge(result.toString()); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 外包遗失
        else if (BillStatusEnum.OUTSRC_LOST.getIndex().equals(billStatus)) {
            batch.setDeliveryCharge(ZERO); //发送费用
            batch.setReceiveCharge(ZERO); //回收费用
            batch.setDefaultCharge("-" + COST_E); //违约扣费
            calculateTotalCharge(batch); // 合计费用
        }
        // 虚假退信
        else if (BillStatusEnum.FAKE.getIndex().equals(billStatus)) {
            batch.setDeliveryCharge(ZERO); //发送费用
            batch.setReceiveCharge(ZERO); //回收费用
            batch.setDefaultCharge("-" + COST_G); //违约扣费
            calculateTotalCharge(batch); // 合计费用
        }
        // 客户投诉
        else if (BillStatusEnum.COMPLAIN.getIndex().equals(billStatus)) {
            batch.setDeliveryCharge(ZERO); //发送费用
            batch.setReceiveCharge(ZERO); //回收费用
            batch.setDefaultCharge("-" + COST_G); //违约扣费
            calculateTotalCharge(batch); // 合计费用
        }
        // 客户遗失
        else if (BillStatusEnum.CUSM_LOST.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 客户拒收
        else if (BillStatusEnum.CUSM_UNRECEIVE.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 客户拒交
        else if (BillStatusEnum.CUSM_UNSEND.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 未回
        else if (BillStatusEnum.UNRETURN.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge("-" + COST_E); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge("-" + COST_E); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }
        // 外包退信
        else if (BillStatusEnum.OUTSRC_BACK.getIndex().equals(billStatus)) {
            batch.setDeliveryCharge(COST_F); //发送费用
            batch.setReceiveCharge(ZERO); //回收费用
            batch.setDefaultCharge(ZERO); //违约扣费
            calculateTotalCharge(batch); // 合计费用
        }
        // 客户自寄
        else if (BillStatusEnum.CUSM_SELF.getIndex().equals(billStatus)) {
            if (AreaTypeEnum.LOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_A); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            } else if (AreaTypeEnum.NONLOCAL.getIndex().equals(batch.getAreaType())) {
                batch.setDeliveryCharge(COST_B); //发送费用
                batch.setReceiveCharge(ZERO); //回收费用
                batch.setDefaultCharge(ZERO); //违约扣费
                calculateTotalCharge(batch); // 合计费用
            }
        }

    }

    private void calculateTotalCharge(OutsrcExpStlmtBatch batch) {
        BigDecimal deliveryCharge = new BigDecimal(batch.getDeliveryCharge());
        BigDecimal receiveCharge = new BigDecimal(batch.getReceiveCharge());
        BigDecimal defaultCharge = new BigDecimal(batch.getDefaultCharge());
        batch.setTotalCharge(deliveryCharge.add(receiveCharge).add(defaultCharge).toString());
    }

}
